package com.imut.lagain.exception;

import com.imut.lagain.common.Result;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.reactive.resource.NoResourceFoundException;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

/**
 * 全局异常处理器
 */

@RestControllerAdvice
public class GlobalExceptionHandler {
    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(GlobalExceptionHandler.class);
    
    @Value("${spring.profiles.active:dev}")
    private String activeProfile;
    
    /**
     * 构建基础响应信息
     */
    private Map<String, Object> buildBaseResponse(String code, String message, Exception ex) {
        Map<String, Object> response = new HashMap<>();
        response.put("success", false);
        response.put("code", code);
        response.put("message", message);
        response.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        
        // 添加请求信息
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                HttpServletRequest request = attributes.getRequest();
                response.put("path", request.getRequestURI());
                response.put("method", request.getMethod());
            }
        } catch (Exception e) {
            log.debug("Failed to get request attributes", e);
        }
        
        // 在开发环境下添加详细错误信息
        if ("dev".equals(activeProfile) && ex != null) {
            response.put("error", ex.getMessage());
            response.put("exception", ex.getClass().getSimpleName());
            
            // 添加堆栈跟踪
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            ex.printStackTrace(pw);
            response.put("stackTrace", sw.toString());
        }
        
        return response;
    }

    /**
     * 处理业务异常
     */
    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<Map<String, Object>> handleBusinessException(BusinessException ex) {
        log.warn("Business exception occurred: {} - Code: {}", ex.getMessage(), ex.getCode(), ex);
        
        Map<String, Object> response = buildBaseResponse(ex.getCode(), ex.getMessage(), ex);
        
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
    }

    /**
     * 处理认证异常
     */
    @ExceptionHandler(AuthenticationException.class)
    public ResponseEntity<Map<String, Object>> handleAuthenticationException(AuthenticationException ex) {
        log.warn("Authentication exception occurred: {}", ex.getMessage(), ex);
        
        Map<String, Object> response = buildBaseResponse("AUTHENTICATION_FAILED", "认证失败", ex);
        
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
    }

    /**
     * 处理权限异常
     */
    @ExceptionHandler(AccessDeniedException.class)
    public ResponseEntity<Map<String, Object>> handleAccessDeniedException(AccessDeniedException ex) {
        log.warn("Access denied exception occurred: {}", ex.getMessage(), ex);
        
        Map<String, Object> response = buildBaseResponse("ACCESS_DENIED", "权限不足", ex);
        
        return ResponseEntity.status(HttpStatus.FORBIDDEN).body(response);
    }

    /**
     * 处理凭证异常
     */
    @ExceptionHandler(BadCredentialsException.class)
    public ResponseEntity<Map<String, Object>> handleBadCredentialsException(BadCredentialsException ex) {
        log.warn("Bad credentials exception occurred: {}", ex.getMessage(), ex);
        
        Map<String, Object> response = buildBaseResponse("BAD_CREDENTIALS", "用户名或密码错误", ex);
        
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
    }

    /**
     * 处理参数验证异常（@Validated）
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, Object>> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        log.warn("Method argument not valid exception occurred", ex);
        
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getAllErrors().forEach((error) -> {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            errors.put(fieldName, errorMessage);
        });
        
        Map<String, Object> response = buildBaseResponse("VALIDATION_FAILED", "参数验证失败", ex);
        response.put("details", errors);
        
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
    }

    /**
     * 处理参数绑定异常
     */
    @ExceptionHandler(BindException.class)
    public ResponseEntity<Map<String, Object>> handleBindException(BindException ex) {
        log.warn("Bind exception occurred", ex);
        
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getAllErrors().forEach((error) -> {
            String fieldName = ((FieldError) error).getField();
            String errorMessage = error.getDefaultMessage();
            errors.put(fieldName, errorMessage);
        });
        
        Map<String, Object> response = buildBaseResponse("BIND_FAILED", "参数绑定失败", ex);
        response.put("details", errors);
        
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
    }

    /**
     * 处理参数类型不匹配异常
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public ResponseEntity<Map<String, Object>> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException ex) {
        log.warn("Method argument type mismatch exception occurred", ex);
        
        Map<String, Object> response = buildBaseResponse("ARGUMENT_TYPE_MISMATCH", 
                String.format("参数 %s 类型不匹配，期望类型为 %s", ex.getName(), ex.getRequiredType()), ex);
        
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
    }

    /**
     * 处理缺少请求参数异常
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public ResponseEntity<Map<String, Object>> handleMissingServletRequestParameterException(MissingServletRequestParameterException ex) {
        log.warn("Missing servlet request parameter exception occurred", ex);
        
        Map<String, Object> response = buildBaseResponse("MISSING_PARAMETER", 
                String.format("缺少必要参数 %s，参数类型为 %s", ex.getParameterName(), ex.getParameterType()), ex);
        
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
    }

    /**
     * 处理请求体不可读异常
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResponseEntity<Map<String, Object>> handleHttpMessageNotReadableException(HttpMessageNotReadableException ex) {
        log.warn("HTTP message not readable exception occurred", ex);
        
        Map<String, Object> response = buildBaseResponse("MESSAGE_NOT_READABLE", "请求体格式不正确", ex);
        
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
    }

    /**
     * 处理404异常
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    public ResponseEntity<Map<String, Object>> handleNoHandlerFoundException(NoHandlerFoundException ex) {
        log.warn("No handler found exception occurred", ex);
        
        Map<String, Object> response = buildBaseResponse("NOT_FOUND", "请求的资源不存在", ex);
        
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
    }

    /**
     * 处理文件上传大小超限异常
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public ResponseEntity<Map<String, Object>> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException ex) {
        log.warn("Max upload size exceeded exception occurred", ex);
        
        Map<String, Object> response = buildBaseResponse("UPLOAD_SIZE_EXCEEDED", "上传文件大小超出限制", ex);
        
        return ResponseEntity.status(HttpStatus.PAYLOAD_TOO_LARGE).body(response);
    }

    /**
     * 处理通用异常
     */
    @ExceptionHandler(Exception.class)
    public ResponseEntity<Map<String, Object>> handleGenericException(Exception ex) {
        log.error("Unexpected exception occurred", ex);
        
        Map<String, Object> response = buildBaseResponse("INTERNAL_ERROR", "系统内部错误", ex);
        
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
    }

    @ExceptionHandler(NoResourceFoundException.class)
    public ResponseEntity<String> handleNoResourceFoundException(NoResourceFoundException ex, HttpServletRequest request) {
        log.error("=== 未找到资源异常 ===");
        log.error("请求方法: {}", request.getMethod());
        log.error("请求URI: {}", request.getRequestURI());
        log.error("请求URL: {}", request.getRequestURL());
        log.error("异常信息: {}", ex.getMessage(), ex);
        
        // 检查是否是API路径被当作静态资源处理
        String requestURI = request.getRequestURI();
        if (requestURI.startsWith("/api/")) {
            log.error("API路径被错误地当作静态资源处理，请检查配置: {}", requestURI);
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                .body("API接口未找到，请检查路径配置: " + requestURI);
        }
        
        return ResponseEntity.status(HttpStatus.NOT_FOUND)
            .body("请求的资源未找到: " + ex.getMessage());
    }
}